今天有新人問說:『為什麼connection要使用using直接呼叫Dispose不就好了?』,所以有了這篇文章,主要寫給Java轉C#或是不了解為何要使用using的工程師。
上面例子是不能直接呼叫Dispose的,之前有做過Java開發的工程師應該會習慣確保資源一定釋放
會編寫try,finally
,像是原本簡單的邏輯建立連線,釋放連線
,需要編寫不少的代碼,以JDBC舉例:
try {
.....
connection.setAutoCommit(false);
.....
// 一連串SQL操作
connection.commit();
} catch(Exception) {
// 發生錯誤,撤消所有變更
if(connection != null) {
try {
connection.rollback();
catch(SQLException ex) {
ex.printStackTrace();
}
}
}
finally {
if(connection != null) {
try {
connection.close();
}
catch(SQLException e) {
e.printStackTrace();
}
}
}
但是在C#我們可以簡單使用using達到同等效果,我們只需要編寫
SqlConnection cn = null;
using ( cn = new SqlConnection(this.Connection.ConnectionString))
{
// 一連串SQL操作
}
為什麼這麼簡單?
因為編譯器幫我們做掉原本需要編寫的代碼,讓我們反編譯這段代碼來看一下,會發現其實底層還是try,finally
,系統幫我們自動補齊代碼,是不是很人性化。
SqlConnection sqlConnection;
SqlConnection cn = sqlConnection = new SqlConnection(連線字串);
try
{
// 一連串SQL操作
}
finally
{
if (sqlConnection != null)
{
((IDisposable)sqlConnection).Dispose();
}
}
這時候系統先生出來說話了:『try,finally幫你做好了,我不可能知道你想要用甚麼邏輯釋放資源,麻煩你去實作Dispose方法,我會幫你呼叫它。』
使用using的類別需要實作IDisposable介面跟實作void Dispose()方法
,告訴系統要照什麼邏輯釋放。像是string類別沒有實作IDisposable是無法使用using,會跳出CS1674 'string': type used in a using statement must be implicitly convertible to 'System.IDisposable'
舉例:
class MyClass : IDisposable {
// ...
private bool disposed = false;
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing) {
if (!this.disposed) {
if (disposing) {
// 釋放資源邏輯
}
disposed = true;
}
}
~MyClass() {
Dispose(false);
}
}
感謝Cymon Dez補充,JDK7以後可以實作java.lang.AutoCloseable介面配合Try-with-resource statement達到相同目的。
我也喜歡用 using
使用 using 還有一個好處,可以確保物件不會在 Dispose 之後被使用
例如
using (var cn = new SqlConnection(this.Connection.ConnectionString))
{
//做了一些事
}
cn.xxx <- 編譯錯誤
而不用 using 則可能會不小心呼叫到 Dispose 後的物件
var cn = new SqlConnection(this.Connection.ConnectionString)
//做了一些事
cn.Dispose();
//又做了一些事
cn.xxx <- 不小心呼叫了 Dispose 後的物件
不過怎麼我認識的工程師都不喜歡用 using
不過怎麼我認識的工程師都不喜歡用 using
對,會寫這篇原因也是新人問說『為什麼不直接呼叫Dispose還要使用using』
using比較方便啊,
我懶得去找怎麼釋放記憶體,
就直接using了 XD
其實就是懶...
工程師有時候越懶反而好 XD